<template>
    <Mapbox :mapOnLoadCB="mapOnLoadCB"></Mapbox>
    <button id='pause'></button>
</template>

<script>
import {ref} from "vue"
import Mapbox from "@/components/common/Mapbox.component.vue"
import MapboxCommonService from "@/service/map/MapboxCommonService"

export default {
    name: "AddAnimateLine.component",
    components: {Mapbox},
    setup() {

        let mapStore = ref({});
        let mapOnLoadCB = (map) => {
            mapStore.value = map;
            MapboxCommonService.setCZBP(map, [0, 0], 0.5)

            // Create a GeoJSON source with an empty lineString.
            let geojson = {
                "type": "FeatureCollection",
                "features": [{
                    "type": "Feature",
                    "geometry": {
                        "type": "LineString",
                        "coordinates": [
                            [0, 0]
                        ]
                    }
                }]
            };

            let speedFactor = 30; // number of frames per longitude degree
            let animation; // to store and cancel the animation
            let startTime = 0;
            let progress = 0; // progress = timestamp - startTime
            let resetTime = false; // indicator of whether time reset is needed for the animation
            let pauseButton = document.getElementById('pause');

            // add the line which will be modified in the animation
            map.addLayer({
                'id': 'line-animation',
                'type': 'line',
                'source': {
                    'type': 'geojson',
                    'data': geojson
                },
                'layout': {
                    'line-cap': 'round',
                    'line-join': 'round'
                },
                'paint': {
                    'line-color': '#ed6498',
                    'line-width': 5,
                    'line-opacity': .8
                }
            });

            startTime = performance.now();

            // click the button to pause or play
            pauseButton.addEventListener('click', () => {
                pauseButton.classList.toggle('pause');
                if (pauseButton.classList.contains('pause')) {
                    cancelAnimationFrame(animation);
                } else {
                    resetTime = true;
                    animateLine();
                }
            });

            // reset startTime and progress once the tab loses or gains focus
            // requestAnimationFrame also pauses on hidden tabs by default
            document.addEventListener('visibilitychange', () => {
                resetTime = true;
            });

            // animated in a circle as a sine wave along the map.
            const animateLine = (timestamp) => {
                if (resetTime) {
                    // resume previous progress
                    startTime = performance.now() - progress;
                    resetTime = false;
                } else {
                    progress = timestamp - startTime;
                }

                // restart if it finishes a loop
                if (progress > speedFactor * 360) {
                    startTime = timestamp;
                    geojson.features[0].geometry.coordinates = [];
                } else {
                    let x = progress / speedFactor;
                    // draw a sine wave with some math.
                    let y = Math.sin(x * Math.PI / 90) * 40;
                    // append new coordinates to the lineString
                    geojson.features[0].geometry.coordinates.push([x, y]);
                    // then update the map
                    map.getSource('line-animation').setData(geojson);
                }
                // Request the next frame of the animation.
                animation = requestAnimationFrame(animateLine);
            }

            animateLine();
        };

        return {
            mapOnLoadCB
        }
    }
}
</script>

<style scoped lang="scss">
#pause {
    position: absolute;
    left: 10px;
    top: 10px
}
#pause::after {
    content: 'Pause';
}
#pause.pause::after {
    content: 'Play';
}
</style>